// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'chrome://resources/cr_elements/cr_view_manager/cr_view_manager.js';
import 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js';
import './profile_picker_main_view.js';
import './profile_picker_shared_css.js';
import './strings.m.js';

import {CrViewManagerElement} from 'chrome://resources/cr_elements/cr_view_manager/cr_view_manager.js';
import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js';
import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';

import {ensureLazyLoaded} from './ensure_lazy_loaded.js';
import {AutogeneratedThemeColorInfo, ManageProfilesBrowserProxy, ManageProfilesBrowserProxyImpl} from './manage_profiles_browser_proxy.js';
import {navigateTo, NavigationMixin, ProfileCreationSteps, Routes} from './navigation_mixin.js';
import {isForceSigninEnabled, isProfileCreationAllowed} from './policy_helper.js';

export interface ProfilePickerAppElement {
  $: {
    viewManager: CrViewManagerElement,
  };
}

const ProfilePickerAppElementBase = I18nMixin(NavigationMixin(PolymerElement));

export class ProfilePickerAppElement extends ProfilePickerAppElementBase {
  static get is() {
    return 'profile-picker-app';
  }

  static get template() {
    return html`{__html_template__}`;
  }

  static get properties() {
    return {
      /**
       * Suggested new profile theme info for the profile creation flow.
       */
      newProfileThemeInfo: {
        type: Object,
        notify: true,
      },
    };
  }

  newProfileThemeInfo: AutogeneratedThemeColorInfo;
  private currentRoute_: Routes|null = null;
  private manageProfilesBrowserProxy_: ManageProfilesBrowserProxy =
      ManageProfilesBrowserProxyImpl.getInstance();

  connectedCallback() {
    super.connectedCallback();
    this.setMinimumSize_();
  }

  onRouteChange(route: Routes, step: string) {
    if (!isProfileCreationAllowed() && route === Routes.NEW_PROFILE) {
      navigateTo(Routes.MAIN);
      return;
    }

    if (step == ProfileCreationSteps.LOAD_FORCE_SIGNIN) {
      assert(
          route == Routes.NEW_PROFILE,
          'LOAD_FORCE_SIGNIN step must be a part of NEW_PROFILE route');
      assert(
          isForceSigninEnabled(),
          'Force signin policy must be enabled to start the force signin flow');
      // The force sign-in flow is displayed in a dialog on top of the main
      // view. Load the main view if it isn't already shown.
      // Do not call `navigateTo(Routes.MAIN)` to not update the history.
      // It's fine to skip `initializeModules()` for the main view since the
      // main view will never be lazy loaded.
      if (this.currentRoute_ !== Routes.MAIN) {
        this.currentRoute_ = Routes.MAIN;
        document.title = this.getDocumentTitle_('mainView');
        this.$.viewManager.switchView('mainView', 'fade-in', 'no-animation');
      }
      // TODO(https://crbug.com/1237418): Add support for ForceSignin on Lacros.
      this.manageProfilesBrowserProxy_.loadSignInProfileCreationFlow(null, '');
      return;
    }

    assert(
        step !== ProfileCreationSteps.LOAD_SIGNIN,
        'LOAD_SIGNIN should not appear in navigation (only used for metrics)');

    const setStep = () => {
      document.title = this.getDocumentTitle_(step);
      this.$.viewManager.switchView(step, 'fade-in', 'no-animation');
    };

    // If the route changed, initialize modules for that route.
    if (this.currentRoute_ !== route) {
      this.currentRoute_ = route;
      this.initializeModules_().then(setStep);
    } else {
      setStep();
    }
  }

  private getDocumentTitle_(step: string): string {
    switch (step) {
      case 'mainView':
        return this.i18n('mainViewTitle');
      case ProfileCreationSteps.PROFILE_TYPE_CHOICE:
        return this.i18n('profileTypeChoiceTitle');
      case ProfileCreationSteps.LOCAL_PROFILE_CUSTOMIZATION:
        return this.i18n('localProfileCreationTitle');
      case 'profileSwitch':
        return this.i18n('profileSwitchTitle');
      // <if expr="lacros">
      case 'accountSelectionLacros':
        return this.i18n('accountSelectionLacrosTitle');
      // </if>
      default:
        return '';
    }
  }

  private initializeModules_(): Promise<any> {
    switch (this.currentRoute_) {
      case Routes.MAIN:
        return Promise.resolve();
      case Routes.NEW_PROFILE:
      // <if expr="lacros">
      case Routes.ACCOUNT_SELECTION_LACROS:
        // </if>
        return Promise.all(
            [this.initializeNewProfileThemeInfo_(), ensureLazyLoaded()]);
      case Routes.PROFILE_SWITCH:
        return ensureLazyLoaded();
      default:
        // |this.currentRoute_| should be set by now.
        assertNotReached();
        return Promise.reject();
    }
  }

  private async initializeNewProfileThemeInfo_(): Promise<void> {
    if (this.newProfileThemeInfo) {
      return Promise.resolve();
    }
    this.newProfileThemeInfo = await this.manageProfilesBrowserProxy_
                                   .getNewProfileSuggestedThemeInfo();
  }

  private setMinimumSize_() {
    this.style.setProperty(
        '--view-min-size', loadTimeData.getString('minimumPickerSize'));
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'profile-picker-app': ProfilePickerAppElement;
  }
}

customElements.define(ProfilePickerAppElement.is, ProfilePickerAppElement);
